package cn.com.thinker.gen.create.service.impl;

import cn.com.thinker.gen.create.properties.ProjectProperties;
import cn.com.thinker.gen.create.service.IProjectService;
import cn.com.thinker.tools.*;
import com.google.common.collect.Lists;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.lang.ArrayUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.directive.Foreach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Created by crazyHC on 2017/6/13.
 */
@Slf4j @Service
@EnableConfigurationProperties(ProjectProperties.class)
@SuppressWarnings({"SpringJavaAutowiringInspection", "SpringAutowiredFieldsWarningInspection"})
public class ProjectServiceImpl implements IProjectService {


    @Autowired
    private ProjectProperties properties;

    @Override
    public void build() throws IOException{

        String[] moduleNames = properties.getModuleNames();
        if(ArrayUtils.isEmpty(moduleNames)){
            throw new RuntimeException("Module Name Must Set Value !");
        }
        String[] sdkNames = properties.getSdkNames();

        String genStrategy = properties.getGenStrategy();
        if(ProjectProperties.GenStrategy.PARENT.name().equalsIgnoreCase(genStrategy)){
            excute("","@_parentName");
        }else if(ProjectProperties.GenStrategy.CHILDREN.name().equalsIgnoreCase(genStrategy)){
            for(String moduleName:moduleNames){
                excute(moduleName,"@_moduleName");
                if(Lists.newArrayList(sdkNames).contains(moduleName)){
                    excute(moduleName,"@_moduleName-sdk");
                }
            }
        }else{
            excute("","@_parentName");
            for(String moduleName:moduleNames){
                excute(moduleName,"@_moduleName");
                if(Lists.newArrayList(sdkNames).contains(moduleName)){
                    excute(moduleName,"@_moduleName-sdk");
                }
            }
        }

    }

    private void excute(String moduleName,String suffix)throws IOException{


        String templateDir = properties.getTemplateDir();

        if(StringUtils.isBlank(templateDir)){
            if(StringUtils.isNotBlank(suffix)){
                templateDir = "classpath*:templates/"+suffix+"/**";
            }else{
                templateDir = "classpath*:templates/**";
            }

            ResourcePatternResolver ctx = new PathMatchingResourcePatternResolver();
            Resource[] resources  = ctx.getResources(templateDir);
            if(null == resources){
                log.error(">>>>>>>>>>>> 没有找到资源文件 <<<<<<<<<<<<<<<<<<");
                return;
            }
            List<Resource> resourcesList = Lists.newArrayList(resources);
            resourcesList.forEach(resource ->{
                String templateName = null;
                try {
                    templateName = resource.getFile().getPath();
                } catch (IOException e) {
                    log.error(ExceptionUtils.getStackTraceAsString(e));
                }
                createFile(moduleName,templateName);
            });
        }else{
            if(StringUtils.isNotBlank(suffix)){
                templateDir = templateDir+"/"+suffix;
            }
            Collection<File> templates  = FileUtils.listFiles(new File(templateDir), TrueFileFilter.INSTANCE,
                    TrueFileFilter.INSTANCE);
            templates.forEach(template ->{
                String templateName = FilenameUtils.separatorsToUnix(template.getPath());
                createFile(moduleName,templateName);
            });

        }
    }
    private void createFile(String moduleName,String templateFile){

        // 判断目录不生成
        if(StringUtils.isBlank(FilenameUtils.getExtension(templateFile))){
            return ;
        }
        // 非分布式，不生成bootstrap.yml
        if(!properties.getDistributed() && FilenameUtils.getName(templateFile).equalsIgnoreCase("bootstrap.yml")){
            return ;
        }

        log.info(">>>>>>>>>>>>templateName:"+templateFile+"<<<<<<<<<<<<<<<<<<");

        String parentName = properties.getParentName();
        templateFile = FilenameUtils.separatorsToUnix(templateFile);
        int i = templateFile.indexOf("templates")+9;
        String templateDir = templateFile.substring(0,i);

        String outputDir = properties.getOutputDir();
        outputDir = FilenameUtils.separatorsToUnix(outputDir);
        if(org.apache.commons.lang3.StringUtils.isBlank(outputDir)){
            outputDir = "./";
        }
        if(templateFile.contains("@_moduleName")){
            outputDir += (File.separator+parentName);
        }

        Map<Object, Object> projectConfig = BeanUtils.Bean2Map(properties);
        projectConfig.put("moduleName",moduleName);
        VelocityContext context = new VelocityContext(projectConfig);
        context.put("StringUtils",StringUtils.class);


        String outputFile = templateFile.replace(templateDir, outputDir);
        String parentNameLower = StringUtils.lowerCase(parentName);
        String moduleNameLower = StringUtils.lowerCase(moduleName);
        if(outputFile.contains("@_parentName") && outputFile.contains("@_moduleName")){
            // 模块输出路径
            outputFile = outputFile.replaceAll("@_parentName",parentNameLower);
        }else{
            // 父目录输出路径
            outputFile = outputFile.replaceFirst("@_parentName",parentName);
        }
        outputFile = outputFile.replaceFirst("@_moduleName",moduleName).replaceAll("@_moduleName",moduleNameLower);
        log.info(String.format("生成文件：%s", outputFile));

        if(StringUtils.isNotBlank(properties.getTemplateDir())){
            // 指定模板目录，按绝对路径方式生成
            VelocityUtils.instance().absPathToFile(context, templateFile, outputFile);
        }else{
            // 没有指定模板目录，按类路径方式生成
            templateFile = templateFile.replace(templateDir,"templates/");
            VelocityUtils.instance().classPathToFile(context, templateFile, outputFile);
        }

    }




}
